package milu.servlets;

import java.io.IOException;
import java.io.InputStream;

import java.util.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import org.apache.commons.fileupload.FileUploadException;
import com.google.appengine.api.datastore.Blob;

import org.apache.commons.io.IOUtils;
import com.google.appengine.api.datastore.*;

import javax.jdo.PersistenceManager;

import milu.models.*;
import milu.*;

/**
 * adds and edits a recipe
 */
public class Add extends HttpServlet {

    public void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        MyUser myUser = (MyUser)request.getAttribute("myUser");
        if(myUser == null) {
            response.sendRedirect("/");
            return;
        }
            
        String[] segments = request.getRequestURI().split("/");
        String recipeId = null;
        if(segments.length >= 3)
            recipeId = segments[2];

        if(recipeId != null) { // editing
            // find the recipe
            PersistenceManager pm = Datastore.getPersistenceManager();
            Key k = KeyFactory.createKey(Recipe.class.getSimpleName(), Long.parseLong(recipeId));
            Recipe recipe = pm.getObjectById(Recipe.class, k);

            // if this recipe doesn't equal the current user that is logged in
            // dont let this person edit
            if(!recipe.getUserKey().equals(myUser.getKey())) {
                response.sendRedirect("/");
                return;
            }

            request.setAttribute("recipe", recipe);
            request.setAttribute("recipeId", recipeId);
        }
            
        request.getRequestDispatcher("/add.jsp").forward(request, response);
    }

    /**
     * adds a new recipe to the system
     * also edits a recipe
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        MyUser user = (MyUser)request.getAttribute("myUser");
		if(user == null) {
			LOG.info("user not logged in");
			response.sendRedirect("");
			return;
		}

		String title = "";
        String content = "", ingredients = "";
        String tagsPar = "";
        String recipeId = "";

        // do upload
		// Get the image representation
        Blob imageBin = null;
        String imageName = "";
		try {
			ServletFileUpload upload = new ServletFileUpload();
			FileItemIterator iter = upload.getItemIterator(request);
			while(iter.hasNext()) {
				FileItemStream item = iter.next();
				InputStream stream = item.openStream();

				if(item.isFormField()) {
					String fieldName = item.getFieldName();
					String fieldValue = new String(IOUtils.toByteArray(stream), "utf-8");
					LOG.info("Got a form field: " +fieldName+" with value: "+fieldValue);
					if(fieldName.equals("title")) title = fieldValue;
					if(fieldName.equals("content")) content = fieldValue;
					if(fieldName.equals("ingredients")) ingredients = fieldValue;
					if(fieldName.equals("tags")) tagsPar = fieldValue;
					if(fieldName.equals("recipeId")) recipeId = fieldValue;
				} else {
					LOG.info("Got an uploaded file: " +item.getFieldName() +", name = "+item.getName());
					// construct our entity objects
					imageBin = new Blob(IOUtils.toByteArray(stream));
                    imageName = item.getName();
				}

			}
		} catch (FileUploadException e){
		}

        // build tags
        String[] tagsStrings = tagsPar.trim().split(" "); // tags are separated by space
        // creating both a set of strings for the Recipe object
        // and a set of Tag(s) to persist them later
        Set<String> tagsAsStrings = new HashSet(Arrays.asList(tagsStrings));

		PersistenceManager pm = Datastore.getPersistenceManager();
        Recipe recipe = null;
        // edit recipe
        if(!recipeId.equals("")) { // we have a recipeid, edit it
            Key k = KeyFactory.createKey(Recipe.class.getSimpleName(), Long.parseLong(recipeId));
            recipe = pm.getObjectById(Recipe.class, k);

            // if this recipe doesn't equal the current user that is logged in
            // dont let this person edit
            if(!recipe.getUserKey().equals(user.getKey())) {
                response.sendRedirect("/");
                return;
            }
        }

		try {
            // validate parameters
            // TODO validate the parameters in case there's weird HTML or javascript
            if((recipeId.equals("") && imageName.equals("")) || title.equals("") || content.equals("") || ingredients.equals("") || tagsPar.equals("")) {
                request.setAttribute("error", "Completa tutto!");

                if(!recipeId.equals(""))
                    request.setAttribute("recipeId", recipeId);

                request.setAttribute("recipe", new Recipe(null, title, new Text(content),new Text(ingredients), tagsAsStrings));
                request.getRequestDispatcher("/add.jsp").forward(request, response);
                return;
            }

            if(recipe == null) // add it if it's not there
                recipe = new Recipe();

            // this will either add or edit it, based on where we got the recipe object from
            recipe.setUserKey(user.getKey());
            recipe.setTitle(title);
            recipe.setContent(new Text(content));
            recipe.setIngredients(new Text(ingredients));
            recipe.setTags(tagsAsStrings);

            // persist tags
            Set<Tag> tags = new HashSet();
            for(int i=0; i<tagsStrings.length; i++) {
                tags.add(new Tag(tagsStrings[i]));
            }
            for(Tag tag : tags)
                pm.makePersistent(tag);

            // do image
            if(!imageName.equals("")) {
                MyImage fullSize = new MyImage(imageName, imageBin);

                // resize thumb
                MyImage thumb = null;
                try {
                    ImageResizer ir = new ImageResizer(imageBin);
                    Blob thumbBin = ir.resize("224", "230");
                    thumb = new MyImage(imageName, thumbBin);
                } catch (java.lang.IllegalArgumentException e) {
                    e.printStackTrace();
                    request.setAttribute("error", "Immagine non valida");
                    if(!recipeId.equals(""))
                        request.setAttribute("recipeId", recipeId);

                    request.setAttribute("recipe", recipe);
                    request.getRequestDispatcher("/add.jsp").forward(request, response);
                    return;
                }

                // persist both of them
                pm.makePersistent(fullSize);
                pm.makePersistent(thumb);

                // set references on recipe
                recipe.setFullImageKey(fullSize.getKey());
                recipe.setThumbKey(thumb.getKey());
            }

            pm.makePersistent(recipe);
        } catch (com.google.apphosting.api.ApiProxy.RequestTooLargeException e) {
            request.setAttribute("error", "Immagine troppo grande. Prova a ridimensionarla.");
            if(!recipeId.equals(""))
                request.setAttribute("recipeId", recipeId);

            request.setAttribute("recipe", recipe);
            request.getRequestDispatcher("/add.jsp").forward(request, response);
		} finally {
			Datastore.finishRequest();
		}
		response.sendRedirect("/");
    }
}
